package com.gopay.bis.service.bank.impl.expay;

import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;

import com.gopay.bis.common.util.BankLogUtils;
import com.gopay.bis.common.util.TransUtil;
import com.gopay.bis.common.util.constants.BisPayConstants;
import com.gopay.bis.manager.bank.BankOrderManager;
import com.gopay.bis.manager.bank.expay.SpdbAdPayManager;
import com.gopay.bis.manager.bank.payconfig.BisBankExtConfigManager;
import com.gopay.bis.service.bank.sms.SmsSupportController;
import com.gopay.bis.service.bank.validcode.ValidCodeSupportController;
import com.gopay.common.Result;
import com.gopay.common.constants.bank.BisBankInterfaceChannel;
import com.gopay.common.constants.bank.QueryNeedCertConstants;
import com.gopay.common.constants.bank.SpdbConstants;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.domain.bank.ExPayBaseMessage;
import com.gopay.common.domain.bank.spdb.adpay.SpdbAdPayBody;
import com.gopay.common.domain.bank.spdb.adpay.SpdbAdPayHeader;
import com.gopay.common.domain.bank.spdb.adpay.SpdbAdPayMessage;
import com.gopay.common.domain.bank.spdb.adpay.req.SinCutQueryReq;
import com.gopay.common.domain.bank.spdb.adpay.res.AcntCheckRes;
import com.gopay.common.domain.bank.spdb.adpay.res.SignInRes;
import com.gopay.common.domain.bank.spdb.adpay.res.SinCutQueryRes;
import com.gopay.common.domain.bank.spdb.adpay.res.SinCutRes;
import com.gopay.common.domain.bis.BaseBisBankExtConfig;
import com.gopay.common.exception.GopayException;
import com.gopay.remote.bank.BisCertificationRemoteService;
import com.gopay.remote.bank.ExPayInteractRemoteService;
import com.gopay.remote.bank.SignInInteractRemoteService;

/**
 * 浦发代扣业务实现类
 * @author jiangxiangjiao
 * @date 2016年11月2日
 */
@SuppressWarnings("unchecked")
public class SpdbAdPayServiceImpl implements ExPayInteractRemoteService,SignInInteractRemoteService {

	private final static Logger logger = LoggerFactory.getLogger(SpdbAdPayServiceImpl.class);
	@Resource(name = "spdbAdPayManager")
	private SpdbAdPayManager spdbAdPayManager;
	@Resource(name = "bankOrderManager")
    private BankOrderManager bankOrderManager;
	@Resource(name = "bisBankExtConfigManager")
    BisBankExtConfigManager bisBankExtConfigManager;
	@Resource(name ="bisCertificationService")
    private BisCertificationRemoteService bisCertificationService;


	// 短信验证码处理类
	public SmsSupportController smsController;
	//验证码处理类
	public ValidCodeSupportController validCodeController;
	

	

	/**
	 * 代扣签约接口 
	 * @param baseMsg
	 * @return
	 * @throws Exception
	 */
	public Result certification(ExPayBaseMessage baseMsg) {
		Result result = new Result(false);
		 SpdbAdPayMessage<SpdbAdPayBody<AcntCheckRes>> message = new SpdbAdPayMessage<SpdbAdPayBody<AcntCheckRes>>();
	     BeanUtils.copyProperties(baseMsg, message);
	        try {
	        	
	        	Map<String, String> param = new HashMap<String, String>();
		        Result res = (Result) bisCertificationService.cardCertification(message);
				   if(res.isSuccess()){
					   if((boolean)res.getModel("flag")){
						   logger.error("============SpdbAdPayServiceImpl==========鉴权通过");
						   // 成功处理
							result.setModel("flag", true);
							result.setModel("retMsg", res.getModel("retMsg"));
					   } else {
						   logger.error("============SpdbAdPayServiceImpl==========鉴权没有通过");
						   result.setModel("flag", false);
						   result.setModel("retMsg", res.getModel("retMsg"));
					   }
				   } else {
					   logger.error("============SpdbAdPayServiceImpl==========鉴权验签失败");
					    //验签失败
						param.put("returnMessage", "银行验签失败");
						
						result.setModel("flag", false);
						result.setErrorMsg("验签失败！");
				   }
			       result.setSuccess(true);
	        } catch (Exception ex) {
	            BankLogUtils.printServiceImplExceptionLog(ex);
	            result.setResultCode(ProcCodeConstants.PROC_CODE_100E6076);
	        }
	        return result;
	}
	
	/**
	 * 代扣接口
	 * 
	 * @param baseMsg
	 * @return ExPayBaseMessage
	 * @throws Exception
	 * 超时等信息需捕获处理
	 */
	public Result payment(ExPayBaseMessage baseMsg) {
		 Result result = new Result(true);
	        baseMsg.setBankOrderId("SP" + TransUtil.processOrderIdTo14Digit(baseMsg.getOrderId()));
	        SpdbAdPayMessage<SpdbAdPayBody<SinCutRes>> message = new SpdbAdPayMessage<SpdbAdPayBody<SinCutRes>>();
	        BeanUtils.copyProperties(baseMsg, message);
	        try {
	        	// 签约
	            message = (SpdbAdPayMessage<SpdbAdPayBody<SinCutRes>>) spdbAdPayManager.payment(message);
	            result.setModel("res", message);
	            result.setDefaultModel(true);
	            Map<String, String> param = new HashMap<String, String>();
	            SpdbAdPayHeader header = message.getHeader();
	            if (StringUtils.equals(SpdbConstants.RESPCODE_SUCCESS, header.getRespCode()) 
	            		&& message.getBody() != null 
	            		&& StringUtils.equals(SpdbConstants.RESPCODE_SUCCESS, message.getBody().getInfo().getRespCode())) {
	                // 验签成功
	                param.put("orderId", baseMsg.getOrderId());
	                param.put("amt", baseMsg.getAmount().toString());
	                param.put("cardType", "Unknown");
	                param.put("notifyNum", "1");
	                param.put("payStatus", "00");
	                param.put("retCode", "00");
	                param.put("retMsg", "验签成功");
	                param.put("isFront", String.valueOf(false));
	                result.setModel("isNotifyCashier", param);
	                result.setSuccess(true);
	                result.setOrderStatus(true);
	                
	               /* String transID = message.getBody().getInfo().getRespTransID();
	                if (StringUtils.isNotEmpty(transID)) {
		                // 支付成功以后，将银行返回的支付平台流水号记录到 bis_bank_main_order 的
		                // BANK_ORDER_ID 中
		                baseMsg.setBankReturnOrderId(transID);
		                logger.error("pay success以后记录平台交易应答流水号：" + transID);
		            }*/
	            } else {
	                // 通知后台地址该订单失败
	            	String errCode = "";
	            	String retMsg = "";	            
	                //浦发代扣通道新增错误码，及错误信息   add by wjq 2017/12/6
	                if(message!=null){
	                	retMsg=message.getReturnInfo();
	                	errCode=message.getBankRetCode();
	                }else{
	                	retMsg="交易失败";
	                }
	                param.put("retMsg", retMsg);
	                param.put("isFront", String.valueOf(false));
	                result.setModel("isNotifyCashier", param);
	                result.setSuccess(true);
	                result.setOrderStatus(false);
	                result.setBankRetCode(errCode);
	            }
	        } catch (GopayException e) {
	            BankLogUtils.printServiceImplExceptionLog(e);
	            result.setResultCode(e.getErrCode());
	        } catch (Exception ex) {
	            BankLogUtils.printServiceImplExceptionLog(ex);
	            result.setResultCode(ProcCodeConstants.PROC_CODE_100E6057);
	        }
	        return result;
	}
	
	/**
	 * 签到交易
	 * @param msg
	 * return Object
	 * @throws GopayException
	 */
	@Override
	public Result signIn(Object msg) throws GopayException {
		Result result = new Result(true);
		logger.error("send object:" + ToStringBuilder.reflectionToString(msg));
		
		ExPayBaseMessage base = new ExPayBaseMessage();
		// 获取银行接口通道配置信息
		BaseBisBankExtConfig bankConfig = bisBankExtConfigManager.findExtConfigByBankChannel(BisBankInterfaceChannel._19);
		// 设置一级私钥路径
        base.setPrivateKeyPath(bankConfig.getIntrMerPravkeyPath());
        // 设置一级私钥密码
        base.setPrivatePwd(bankConfig.getIntrMerPravkeyPwd());
        // 设置二级私钥路径
        base.setPrivateKeyPath2nd(bankConfig.getIntrMer2ndPravkeyPath());
        // 设置二级私钥密码
        base.setPrivatePwd2nd(bankConfig.getIntrMer2ndPravkeyPwd());
        // 设置公钥路径
        base.setPublicKeyPath(bankConfig.getIntrBankPubkeyPath());
        // 设置商户号
        base.setMerID(bankConfig.getIntrMernum1());
        // 设置二级商户号
        base.setMerID2nd(bankConfig.getIntrMernum2());
        // 设置结算账户网点联行号
        base.setBranchCode(bankConfig.getBranchCode());
        // 设置银行支付地址
        base.setPayUrl(bankConfig.getPayUrl());
        // 设置支付后台通知地址
        base.setPayRuturnUrl(bankConfig.getPayRuturnUrl());
        // 设置支付后前通知地址
        base.setPayNotifyUrl(bankConfig.getPayNotifyUrl());
		SpdbAdPayMessage<SpdbAdPayBody<SignInRes>> resMsg = (SpdbAdPayMessage<SpdbAdPayBody<SignInRes>>) spdbAdPayManager.SignIn(base);
		logger.error("receive object:" + ToStringBuilder.reflectionToString(resMsg));
		SpdbAdPayHeader header = resMsg.getHeader();
		if(StringUtils.equals(SpdbConstants.RESPCODE_SUCCESS, header.getRespCode()) && resMsg.getBody() != null){
			result.setSuccess(true);
			result.setDefaultModel(resMsg.getBody().getInfo().getKeyValue());
		}else{
			result.setSuccess(false);
		}
		return result;
	}

	/**
	 * 代扣查询接口
	 * 
	 * @param baseMsg
	 * @return
	 * @throws Exception
	 */
	public Result queryOrder(ExPayBaseMessage baseMsg) {
	    Result result = new Result(false);
	    
	    SpdbAdPayMessage<SpdbAdPayBody<SinCutQueryReq>> sinCutQueryReq = new SpdbAdPayMessage<SpdbAdPayBody<SinCutQueryReq>>();
        BeanUtils.copyProperties(baseMsg, sinCutQueryReq);
	    
        try {
            SpdbAdPayMessage<SpdbAdPayBody<SinCutQueryRes>> message  = (SpdbAdPayMessage<SpdbAdPayBody<SinCutQueryRes>>) spdbAdPayManager.query(sinCutQueryReq);
            SinCutQueryRes sinCutQueryRes = message.getBody().getInfo();
            result.setDefaultModel(sinCutQueryRes);
            result.setSuccess(true);
            
            Map<String, String> param = new HashMap<String, String>();
            param.put("orderId", baseMsg.getOrderId());
            
            SpdbAdPayHeader header = message.getHeader();
            if(!SpdbConstants.SPDB_ADPAY_RESPCODE_SUCCESS.equals(header.getRespCode())){
             // 报文头的系统返回码不为“00”，则报文体为空
                param.put("returnCode", BisPayConstants.QUERYSTATE_FAIL);
                param.put("returnMessage", "银行返回对账结果为空");
                param.put("tradeState", BisPayConstants.TRADESTATE_OTHER);
                result.setModel("queryResult", param);
                //BankLogUtils.printExPayManagerQuerySendLog(message);
                return result;
            }else{
            	//SinCutQueryRes sinCutQueryRes = message.getBody().getInfo();
                if(SpdbConstants.SPDB_ADPAY_RESPCODE_SUCCESS.equals(sinCutQueryRes.getRespCode())
                        || SpdbConstants.SPDB_ADPAY_RESPCODE_END.equals(sinCutQueryRes.getRespCode())){
                 // 成功处理
                    param.put("returnCode", BisPayConstants.QUERYSTATE_SUCCESS);
                    param.put("tradeState", BisPayConstants.TRADESTATE_SUCCESS);
                    param.put("returnMessage", "交易成功");
                    
                    result.setOrderStatus(true);
					result.setModel("flag", true);
                }else if(SpdbConstants.SPDB_ADPAY_RESPCODE_PROCESSING.equals(sinCutQueryRes.getRespCode())
                		|| SpdbConstants.SPDB_ADPAY_RESPCODE_UNKNOWN.equals(sinCutQueryRes.getRespCode())
                		|| SpdbConstants.SPDB_ADPAY_RESPCODE_LOCKED.equals(sinCutQueryRes.getRespCode())){
                 // 处理中
                    param.put("returnCode", BisPayConstants.QUERYSTATE_SUCCESS);
                    param.put("tradeState", BisPayConstants.TRADESTATE_OTHER);
                    param.put("returnMessage", "交易处理中");
                }else if(SpdbConstants.SPDB_ADPAY_RESPCODE_NOTEXIST.equals(sinCutQueryRes.getRespCode())){
                 // 交易不存在
                	//如果状态是原交易不存在，并且bis_bank_main_order订单表状态为00，就返回错误信息
					/*BankOrder bankOrder = bankOrderManager.getBankOrderById(baseMsg.getOutOrderId());
					if(BankOrderStatus.PROCESS.equals(bankOrder.getOrderStatus())){
						throw new GopayException(ProcCodeConstants.PROC_CODE_100E5041);
					}*/
                    param.put("returnCode", BisPayConstants.QUERYSTATE_SUCCESS);
                    param.put("tradeState", BisPayConstants.TRADESTATE_OTHER);
                    param.put("returnMessage", "交易不存在");
                }else{
                 // 交易失败
                    param.put("returnCode", BisPayConstants.QUERYSTATE_SUCCESS);
                    param.put("tradeState", BisPayConstants.TRADESTATE_FAIL);
                    param.put("returnMessage", "交易失败");
                    
                    result.setOrderStatus(false);
					result.setModel("flag", false);
                }
                result.setModel("queryResult", param);
            }
            
        } catch (GopayException e) {
            BankLogUtils.printServiceImplExceptionLog(e);
            result.setResultCode(e.getErrCode());
        } catch (Exception ex) {
            BankLogUtils.printServiceImplExceptionLog(ex);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100E6058);
        }
        return result;
	}
	/**
	 * 发送短信验证码接口 
	 */	
	public Result sendSms(ExPayBaseMessage baseMsg) {
	    Result result = new Result(false);
	    SpdbAdPayMessage message = new SpdbAdPayMessage();
        BeanUtils.copyProperties(baseMsg, message);
        try {
            Map<String, String> smsRes = smsController.sendSMS(message);
            if (ProcCodeConstants.PROC_CODE_100E6102.equals(smsRes.get("resCode"))) {
                // 短信发送成功
                result.setModel("flag", true);
            } else {
                // 短信发送失败
                result.setModel("flag", false);
            }
            result.setModel("sendCount", smsRes.get("sendCount"));
            result.setModel("retMsg", smsRes.get("retMsg"));
            result.setModel("resCode", smsRes.get("resCode"));
            result.setResultCode(smsRes.get("resCode"));
            result.setSuccess(true);
        } catch (Exception ex) {
            BankLogUtils.printServiceImplExceptionLog(ex);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100E6077);
        }
        return result;
	}

	/**
	 * 校验短信
	 */
	public Result checkSms(ExPayBaseMessage baseMsg) {
	    Result result = new Result(false);
	    SpdbAdPayMessage message = new SpdbAdPayMessage();
        BeanUtils.copyProperties(baseMsg, message);
        try {
            Map<String, String> smsRes = smsController.checkSMS(message);
            if (ProcCodeConstants.PROC_CODE_100E6091.equals(smsRes.get("resCode"))) {
                // 验证通过
                result.setModel("flag", true);               
            } else {
                // 验证失败
                result.setModel("flag", false);
                if(!ProcCodeConstants.PROC_CODE_100E6099.equals(smsRes.get("resCode"))){
                    Map<String, String> freezeRes = smsController.freezeCard(message);
                    if(freezeRes != null)
                        smsRes = freezeRes;
                }
            }
            result.setModel("failCount", smsRes.get("failCount"));
            result.setModel("retMsg", smsRes.get("retMsg"));
            result.setModel("resCode", smsRes.get("resCode"));
            result.setResultCode(smsRes.get("resCode"));
            result.setSuccess(true);
        } catch (Exception ex) {
            BankLogUtils.printServiceImplExceptionLog(ex);
            result.setResultCode(ProcCodeConstants.PROC_CODE_100E6078);
        }
        return result;
	}


	/**
	 * 返回结果处理接口
	 */
	public Result verify(ExPayBaseMessage baseMsg) {
		return null;
	}

	@Override
	public Result refund(ExPayBaseMessage baseMsg) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Result cancel(ExPayBaseMessage baseMsg) {
		// TODO Auto-generated method stub
		return null;
	}
	@Override
	public Result sign(ExPayBaseMessage baseMsg) {
		return null;
	}
	
	/**
     * 是否需要cvv2
     */
	public Result queryCvn(ExPayBaseMessage baseMsg) {
		 Result result = new Result();
	        result.setSuccess(true);
	        result.setModel("flag", true);
	        result.setModel("isQueryCVN", SpdbConstants.SPDB_EXPAY_NOTQUERYCVN);
	        return result;
	}
	
	@Override
	public Result treatyQuery(ExPayBaseMessage baseMsg) {
		// TODO Auto-generated method stub
		return null;
	}
	
	public SpdbAdPayManager getSpdbAdPayManager() {
		return spdbAdPayManager;
	}

	public void setSpdbAdPayManager(SpdbAdPayManager spdbAdPayManager) {
		this.spdbAdPayManager = spdbAdPayManager;
	}

	public SmsSupportController getSmsController() {
		return smsController;
	}

	public void setSmsController(SmsSupportController smsController) {
		this.smsController = smsController;
	}

	public ValidCodeSupportController getValidCodeController() {
		return validCodeController;
	}

	public void setValidCodeController(ValidCodeSupportController validCodeController) {
		this.validCodeController = validCodeController;
	}

	public BankOrderManager getBankOrderManager() {
		return bankOrderManager;
	}

	public void setBankOrderManager(BankOrderManager bankOrderManager) {
		this.bankOrderManager = bankOrderManager;
	}

	@Override
	public Result queryNeedCert(ExPayBaseMessage baseMsg) {
		Result result = new Result();
        result.setSuccess(true);
        result.setModel("NeedMark", QueryNeedCertConstants.QUERY_RESULT_NONEED);
        return result;
	}

	@Override
	public Result refundBack(ExPayBaseMessage baseMsg) {
		// TODO Auto-generated method stub
		return null;
	}



	

}
